package com.tich.program.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tich.api.client.CommonClient;
import com.tich.constant.ExceptionConstant;
import com.tich.constant.RabbitMqConstant;
import com.tich.enumration.IsStatus;
import com.tich.exception.ProgramCategoryNotFoundException;
import com.tich.exception.ProgramNotFoundException;
import com.tich.exception.ProgramTicketSellingRejectUpdateException;
import com.tich.program.domain.dto.*;
import com.tich.program.domain.entity.*;
import com.tich.program.domain.vo.*;
import com.tich.program.mapper.*;
import com.tich.program.service.IProgramService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tich.utils.IdGeneratorUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

@Service
public class ProgramServiceImpl extends ServiceImpl<ProgramMapper, Program> implements IProgramService {

    @Autowired
    private ProgramMapper programMapper;
    @Autowired
    private ProgramShowtimeMapper programShowtimeMapper;
    @Autowired
    private ProgramTicketMapper programTicketMapper;
    @Autowired
    private ProgramCategoryMapper programCategoryMapper;
    @Autowired
    private TicketCategoryMapper ticketCategoryMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private CommonClient commonClient;

    /**
     * 查询所有节目的简略信息
     * @param programSimpleSelectDTO
     * @return
     * */
    public ProgramSimpleVO querySimpleProgram(ProgramSimpleSelectDTO programSimpleSelectDTO) {
        //构造查询条件,查询count个上架的节目信息
        LambdaQueryWrapper<Program> lambdaQueryWrapper = Wrappers.lambdaQuery(Program.class)
                .eq(Program::getCategoryId, programSimpleSelectDTO.getCategoryId())
                .lt(Program::getUpdateTime, programSimpleSelectDTO.getCursor())
                .eq(Program::getStatus, IsStatus.YES.getCode())
                .orderByDesc(Program::getUpdateTime);
        //自定义SQL,查询count个节目信息
        List<Program> programs = programMapper.querySimpleProgram(lambdaQueryWrapper, programSimpleSelectDTO);
        //创建返回体
        ProgramSimpleVO programSimpleVO = new ProgramSimpleVO();
        programSimpleVO.setCursor(programs.get(programs.size() - 1).getUpdateTime());
        List<ProgramSimpleSelectVO> programSimpleSelectVOS = new ArrayList<>();
        for (Program program : programs) {
            //查询详细时间信息
            ProgramShowtime programShowtime = programShowtimeMapper.selectById(program.getId());
            //查找最低的票价
            LambdaQueryWrapper<ProgramTicket> queryWrapper = Wrappers.lambdaQuery(ProgramTicket.class).eq(ProgramTicket::getProgramId, program.getId());
            Integer minPrice = programTicketMapper.getMinPriceByProgramId(queryWrapper);
            //封装返回数据
            ProgramSimpleSelectVO programSimpleSelectVO = ProgramSimpleSelectVO.builder()
                    .id(program.getId())
                    .categoryId(program.getCategoryId())
                    .title(program.getTitle())
                    .poster(program.getPoster())
                    .city(commonClient.getAreaNameById(program.getCityId()).getName())
                    .showDayTime(programShowtime.getShowDayTime())
                    .showWeekTime(programShowtime.getShowWeekTime())
                    .minPrice(minPrice)
                    .build();
            programSimpleSelectVOS.add(programSimpleSelectVO);
        }
        programSimpleVO.setDatas(programSimpleSelectVOS);
        return programSimpleVO;
    }

    /**
     * 新增节目业务
     * @param programSaveDTO
     * */
    @Transactional
    public void saveProgram(ProgramSaveDTO programSaveDTO) {
        ProgramDTO programDTO = programSaveDTO.getProgramDTO();
        //查询是否有相应的节目种类,不存在则抛出异常
        LambdaQueryWrapper<ProgramCategory> lambdaQueryWrapper = Wrappers.lambdaQuery(ProgramCategory.class)
                .eq(ProgramCategory::getId, programDTO.getCategoryId());
        if(!programCategoryMapper.exists(lambdaQueryWrapper)){
            throw new ProgramCategoryNotFoundException(ExceptionConstant.PROGRAM_CATEGORY_NOT_FOUND);
        }
        //调用工具类自动生成节目id
        Long programId = IdGeneratorUtil.getInstance().nextId();
        //构建节目实体类，并存入数据库
        Program program = BeanUtil.copyProperties(programDTO, Program.class);
        program.setId(programId);
        program.setActors(JSONUtil.toJsonStr(programDTO.getActorList()));
        programMapper.insert(program);
        //构造节目详细时间实体类，并存入数据库
        ProgramShowTimeDTO programShowTimeDTO = programSaveDTO.getProgramShowTimeDTO();
        ProgramShowtime programShowtime = BeanUtil.copyProperties(programShowTimeDTO, ProgramShowtime.class);
        programShowtime.setProgramId(programId);
        programShowtime.setShowWeekTime(Week.of(DateUtil.dayOfWeek(DateUtil.date(programShowtime.getShowDayTime()))).toChinese());
        programShowtimeMapper.insert(programShowtime);
    }

    /**
     * 修改节目信息
     * @param programUpdateDTO
     * */
    @Transactional
    public void updateProgram(ProgramUpdateDTO programUpdateDTO) {
        ProgramDTO programDTO = programUpdateDTO.getProgramDTO();
        //查询节目信息,并判断是否存在
        Program programSelect = programMapper.selectById(programDTO.getId());
        if(BeanUtil.isEmpty(programSelect)){
            throw new ProgramNotFoundException(ExceptionConstant.PROGRAM_NOT_FOUND);
        }
        //TODO 如果已下架则禁止修改
        //TODO 如果已经开始售票则禁止修改，但实际业务不符合要求
        if(programSelect.getSaleStartTime().isBefore(LocalDateTime.now())){
            throw new ProgramTicketSellingRejectUpdateException(ExceptionConstant.PROGRAM_TICKET_SELLING_REJECT_UPDATE);
        }
        Program program = BeanUtil.copyProperties(programDTO, Program.class);
        program.setUpdateTime(LocalDateTime.now());
        if(!programDTO.getActorList().isEmpty()){
            program.setActors(JSONUtil.toJsonStr(programDTO.getActorList()));
        }
        programMapper.updateById(program);

        //构建节目时间修改实体，判断是否要修改演出时间
        ProgramShowTimeDTO programShowTimeDTO = programUpdateDTO.getProgramShowTimeDTO();
        if(!BeanUtil.isEmpty(programShowTimeDTO)){
            ProgramShowtime programShowtime = BeanUtil.copyProperties(programShowTimeDTO, ProgramShowtime.class);
            if(programShowTimeDTO.getShowDayTime() != null){
                programShowtime.setShowWeekTime(Week.of(DateUtil.dayOfWeek(DateUtil.date(programShowtime.getShowDayTime()))).toChinese());
            }
            programShowtime.setProgramId(program.getId());
            programShowtime.setUpdateTime(LocalDateTime.now());
            programShowtimeMapper.updateById(programShowtime);
        }
    }

    /**
     * 删除节目信息
     * @param id
     * */
    @Transactional
    public void deleteProgram(Long id) {
        //1.先查询是否有相应的节目
        Program program = programMapper.selectById(id);
        if(BeanUtil.isEmpty(program)){
            throw new ProgramNotFoundException(ExceptionConstant.PROGRAM_NOT_FOUND);
        }
        //2.删除节目
        programMapper.deleteById(id);
        //3.查询节目时间信息
        ProgramShowtime programShowtime = programShowtimeMapper.selectById(id);
        //4.删除节目时间信息
        programShowtimeMapper.deleteById(id);
        //5.查询节目门票信息
        LambdaQueryWrapper<ProgramTicket> queryWrapper = Wrappers.lambdaQuery(ProgramTicket.class).eq(ProgramTicket::getProgramId, id);
        List<ProgramTicket> programTickets = programTicketMapper.selectList(queryWrapper);
        //6.删除节目门票信息
        programTicketMapper.delete(queryWrapper);
        //7.组装节目删除map
        ProgramMQDeleteDTO programMQDeleteDTO = new ProgramMQDeleteDTO();
        programMQDeleteDTO.setProgram(program);
        programMQDeleteDTO.setProgramShowtime(programShowtime);
        programMQDeleteDTO.setProgramTickets(programTickets);
        //7.将消息发送至交换机
        rabbitTemplate.convertAndSend(RabbitMqConstant.PROGRAM_DIRECT,
                RabbitMqConstant.PROGRAM_DELETE_KEY,
                programMQDeleteDTO);
        //TODO 去查找相对应的订单，并修改
    }

    /**
     * 查询节目详细信息
     * @param id
     * @return
     * */
    public ProgramSelectVO selectProgram(Long id) {
        //查询节目信息
        Program program = programMapper.selectById(id);
        //如果不存在则抛出异常
        if(BeanUtil.isEmpty(program)){
            throw new ProgramNotFoundException(ExceptionConstant.PROGRAM_NOT_FOUND);
        }
        ProgramVO programVO = BeanUtil.copyProperties(program, ProgramVO.class);
        programVO.setCity(commonClient.getAreaNameById(program.getCityId()).getName());
        programVO.setActorList(JSONUtil.toList(program.getActors(), String.class));
        //查询节目时间信息
        ProgramShowtime programShowtime = programShowtimeMapper.selectById(id);
        ProgramShowTimeVO programShowTimeVO = BeanUtil.copyProperties(programShowtime, ProgramShowTimeVO.class);
        //查询节目门票
        List<ProgramTicketSelectVO> programTicketSelectVOS = programTicketMapper.selectProgramTickets(id);
        //构建返回体
        return ProgramSelectVO.builder()
                .programVO(programVO)
                .programShowTimeVO(programShowTimeVO)
                .programTicketSelectVOS(programTicketSelectVOS)
                .build();
    }

}
